//
//  Functions.m
//  Wi-Fi Party remade-1
//
//  Created by Vieta Ken on 2021/2/26.
//

#import "Functions.h"

void check_int(int num, int noerr, char* msg){
    if(num!=noerr){
        printf("%s", msg);
        exit(1);
    }
}

void check_bool(bool succeeded, char* msg){
    if(!succeeded){
        printf("%s", msg);
        exit(1);
    }
}

void check_nil(id whatever, char* msg){
    if(whatever!=nil){
        printf("%s",msg);
        exit(1);
    }
}

void cleanup(NSMutableDictionary *recv_dict){
    if([recv_dict count]>0){
        for(NSNumber *key in recv_dict){
            Queue* q=recv_dict[key];
            if(q->empty>=DEL_BEFORE_EMPTY){
                [recv_dict removeObjectForKey:key];
            }
    }
    }
}

void mix_audio_streams(NSArray *tracks,int length,Queue *output){
    signed char linearTracks[tracks.count][length];
    signed char result[length];
    int efficientLength[tracks.count];
    memset(result, 0x00, length);
    //Fetch
    for(int i=0;i<tracks.count;i++) efficientLength[i] = [tracks[i] readAndWriteTo:linearTracks[i] size:length];
    //Mix
    for(int track_index=0;track_index<tracks.count;track_index++)
        for(int byte_index=0;byte_index<length;byte_index++)
            result[byte_index] += linearTracks[track_index][byte_index*efficientLength[track_index]/length]/tracks.count;
    
    [output writeData:result size:length];
}



void receive_from_udp(int receive_socket,NSMutableDictionary *recv_dict,dispatch_queue_t dispatch_queue){
    struct sockaddr_in *from_addr=malloc(sizeof(struct sockaddr_in));
    void *recv_buffer=malloc(BUFFER_SIZE);
    long *efficient_payload=malloc(sizeof(long));
    static NSMutableDictionary* last_times;
    
    if(last_times==nil) last_times=[[NSMutableDictionary alloc] init];
    {
        unsigned int len=sizeof(*from_addr);
        *efficient_payload=recvfrom(receive_socket,recv_buffer,BUFFER_SIZE, 0,(struct sockaddr *)from_addr, &len);
    }
    partyPacket *packet=[[partyPacket alloc] init:*efficient_payload received:recv_buffer];
    NSNumber *from_ip=[[NSNumber alloc] initWithUnsignedInt:from_addr->sin_addr.s_addr];
    NSNumber *packet_number=[[NSNumber alloc] initWithUnsignedLongLong:*[packet getPacketNumber]];
    
    if(![[last_times allKeys] containsObject:from_ip]   ||
       [packet_number intValue]>[last_times[from_ip] intValue] ||
       [packet_number intValue]==0){
        last_times[from_ip]=packet_number;
        dispatch_async(dispatch_queue, ^{
            if(![[recv_dict allKeys] containsObject:from_ip]){
                recv_dict[from_ip]=[[Queue alloc] init];
            }
            [recv_dict[from_ip] writeData:[packet getPayloadAddr] size:(int)[packet getLength]];
            free(from_addr);
            free(recv_buffer);
            free(efficient_payload);
        });
    }else{
        free(from_addr);
        free(recv_buffer);
        free(efficient_payload);
    }
}

